package jess;

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.logging.FileHandler;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

import utils.CassandraJMXProxy;
import utils.ConfigProperties;
import utils.ObjectPersistentUtil;
import cassandra.Action;
import cassandra.ColumnFamilyThreadPool;
import cassandra.Ring;
import cassandra.RingStatistics;
import exception.RuleBasedMonitoringException;

public class JessRuleEngine {
	private Rete engine;
	private WorkingMemoryMarker marker;
	private ObjectPersistentUtil opUtil;
	private CassandraJMXProxy monitor;



	public JessRuleEngine() throws JessException, RuleBasedMonitoringException {

		opUtil = new ObjectPersistentUtil();
		monitor = CassandraJMXProxy.getInstance();

		// Create a Jess rule engine
		engine = new Rete();
		engine.reset();


		engine.batch("cassandra.clp");

		marker = engine.mark();
	}

	public Iterator<Action> run() throws JessException, RuleBasedMonitoringException {

		engine.resetToMark(marker);

		Ring ring = monitor.getRingImage();
		//Ring ring = getTestRing();

		RingStatistics rSta;
		try {
			rSta = opUtil.recoverRingStatistics();
		} catch (RuleBasedMonitoringException e) {
			// TODO Auto-generated catch block
			if (e.getCause() instanceof FileNotFoundException) {

				rSta = new RingStatistics();
				rSta.setNodeNumber(ring.getNodeNumber());
			} else {
				throw e;
			}
		} 

		List<ColumnFamilyThreadPool> pools = monitor.getColumnThreadPools();

		engine.addAll(pools);
		engine.add(ring);
		engine.add(rSta);

		// Fire the rules that apply to this order
		engine.run();

		opUtil.persistRingStatistics(rSta);

		// Return the list of offers created by the rules
		return engine.getObjects(new Filter.ByClass(Action.class));
	}


	public void getLogger () throws RuleBasedMonitoringException {
		boolean append = true;
		FileHandler fh;
		try {
			String deploymentDir = ConfigProperties.getInstance().getDeploymentDir();
			fh = new FileHandler(deploymentDir + "rule-based-monitoring.log", append);
			fh.setFormatter(new SimpleFormatter());
			Logger logger = Logger.getLogger(Action.class.getName());
			logger.addHandler(fh);
		} catch (Exception e) {
			throw (new RuleBasedMonitoringException(e));
		}      
	}

	private Ring getTestRing () {

		List<String> downNodes =new ArrayList<String>(); 
		downNodes.add("123");
		downNodes.add("124"); 
		return new Ring(Collections.EMPTY_MAP, Collections.EMPTY_LIST, downNodes, Collections.EMPTY_MAP);

	}

	public static void main (String[] args) {
		try {
			JessRuleEngine engine = new JessRuleEngine();
			engine.getLogger();

			Iterator<Action> operations = engine.run();
			int index = 0;
			while (operations.hasNext()) {
				operations.next().call();
				index++;
			}

		} catch (JessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (RuleBasedMonitoringException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}